﻿#ifndef TESTRUNNER_H
#define TESTRUNNER_H

#include <QObject>
#include <QSharedPointer>
#include <QHash>
#include <QWaitCondition>
#include <QMutex>
#include <QString>
#include <atomic>
#include <memory>
#include "itestflow.h"

#include "levelscanningflowsession.h"

// 前向声明可执行计划类型（快照）
namespace Exec {
struct TestPlan; // 仅前向声明
using TestPlanPtr = QSharedPointer<const TestPlan>;
} // namespace Exec

// 会话包前向声明（具体定义在 cpp）
struct SessionBundle;
using SessionBundlePtr = std::shared_ptr<SessionBundle>;
/**
 * TestRunner
 * 作用：
 *  - 运行于工作线程中（moveToThread），负责按计划执行测试：
 *      - 单点测量、向前/向后扫描
 *      - 跨子区间前安全停止射频、提示人工切换硬件（例如天线），等待UI确认后继续
 *      - 统一的“暂停/恢复/停止”控制
 *  - 测试流程逻辑通过 ITestFlow 策略接口注入（如辐射法/传导法），支持多流程扩展
 *  - 会话复用：同一硬件（hw）只创建一次会话对象，切回时直接复用，提高效率
 *
 * 使用方法（UI侧）：
 *  1）runner->setPlan(planPtr)            设置计划（包含 flowKind 与 subranges）
 *  2）runner->setCursor(subIdx, freqIdx)  设置当前游标位置
 *  3）runner->runSingle()/runSweepForward()/runSweepBackward() 开始测试
 *  4）跨子区间时会发出 manualChangeRequired 提示；UI 弹窗后调用 runner->resume() 或 runner->stop()
 *  5）在 UI 中连接 stateChanged/pointMeasured/errorOccurred/logMessage/sweepFinished 信号刷新界面
 */
class TestRunner : public QObject
{
    Q_OBJECT
public:
    explicit TestRunner(QObject *parent = nullptr);

public slots:
    /**
     * 设置测试计划快照（只读）
     * - 会清空当前会话池与活动会话
     * - 重置游标
     * - 根据计划里的 flowKind 选择对应的流程策略
     */
    void setPlan(Exec::TestPlanPtr testPlanPointer);

    /**
     * 设置当前游标（子区间索引 + 频点索引）
     * - 不做边界检查，真正使用时会做校正
     */
    void setCursor(int subrangeIndex, int frequencyIndex);

    /**
     * 单点测量：按当前游标进行一次测量
     */
    void runSingle();

    /**
     * 向前扫描：从当前游标开始，频点 +1，跨子区间时触发人工切换
     */
    void runSweepForward();

    /**
     * 向后扫描：从当前游标开始，频点 -1，跨子区间时触发人工切换
     */
    void runSweepBackward();

    void runLevelScanning(LevelScanningConfig config);

    /**
     * 停止请求：尽快终止当前执行（在安全点检查并退出）
     * - 会唤醒暂停等待
     */
    void stop();

    /**
     * 暂停请求：立即进入暂停态，先安全关闭RF，再等待 UI 调用 resume() 或 stop()
     */
    void pause();

    /**
     * 恢复请求：从暂停中继续执行
     */
    void resume();
    // 安全收尾：静默所有射频，关闭所有会话，清空资源（在工作线程调用）
    void shutdownAndRelease();

signals:
    /**
     * 状态变化：可用于 UI 状态显示与按钮可用性控制
     * 取值： "Idle" / "Running" / "Paused"
     */
    void stateChanged(QString stateText);

    /**
     * 单点测量结果：UI 拿到结果更新图形/表格
     */
    void pointMeasured(MeasurementPoint measurementPoint);

    /**
     * 扫描完成：一次完整的向前/向后扫描结束后发出
     */
    void sweepFinished();

    /**
     * 错误信息：遇到任何错误（会话创建失败、设备异常、参数异常等），发此信号
     */
    void errorOccurred(QString errorText);

    /**
     * 日志：可选，用于追踪步骤（设置频率、会话复用/重建、状态切换等）
     */
    void logMessage(QString line);

    /**
     * 人工切换提示：跨子区间前触发，让 UI 弹窗提示用户更换硬件
     * UI 处理：
     *  - 用户点击“继续”：调用 runner->resume()
     *  - 用户点击“停止”：调用 runner->stop()
     */
    void manualChangeRequired(QString title, QString message);
    // 实时进度（同线程队列到 UI）
    void pointProgress(const MeasurementPoint &p);
    void sig_levelScanData(const LevelScanningData &p);
    void sig_updateDeviceStatus(const DeviceMeasureStatus &p);

private:
    /**
     * 公共扫描骨架：isForwardDirection=true 表示向前（频点+1），false 向后（频点-1）
     * - 内部负责跨子区间人工切换、安全静默、恢复/停止逻辑
     */
    void sweep(bool isForwardDirection);

    /**
     * 在暂停状态下阻塞等待，直到 resume() 或 stop()
     * - 工作线程内部使用，避免忙等
     */
    void waitIfPausedOrStopped();

    /**
     * 确保当前子区间会话已就绪（按硬件键复用/新建）
     * - 成功后 activeSession_ 可用
     */
    bool ensureSessionsForCurrentSubrange();

    /**
     * 安全静默：关闭可能产生射频输出的设备（信号源 RF Off、功放 Standby 等）
     */
    void safeMuteAllOutputs();

    /**
     * 在指定子区间/频点执行一次测量（调用 ITestFlow::measureOnePoint）
     * - 成功：填充 outPointResult，返回 true
     * - 失败：发错误信号，并返回 false
     */
    bool measurePointAt(int subrangeIndex, int frequencyIndex);

    // 安全关闭并释放当前会话
    void teardownActiveSession_();

private:
    // 计划快照（只读）
    Exec::TestPlanPtr testPlan_;

    // 当前使用的流程策略实例（通过 FlowFactory 按计划 flowKind 创建）
    std::unique_ptr<ITestFlow> testFlow_;
    std::unique_ptr<LevelScanningFlow> levelScanningFlow_;
    // 当前游标：子区间与频点索引
    int currentSubrangeIndex_ = 0;
    int currentFrequencyIndex_ = 0;

    // 停止/暂停控制
    std::atomic<bool> isStopRequestedAtomicFlag_ {false}; // 停止请求标志（原子）
    bool isPauseRequested_ = false;                       // 是否请求暂停
    bool isPaused_ = false;                               // 当前是否处于“已暂停”状态
    QMutex pauseMutex_;
    QWaitCondition pauseConditionVariable_;

    // 仅保留“当前会话”，不做会话池
    TestFlowSessionPtr activeSession_; // 当前会话（对应当前子区间硬件）
};

#endif // TESTRUNNER_H
